home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / gfx / 3d / irit50src.lha / irit5 / symb_lib / bsp_sym.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-14  |  17.9 KB  |  531 lines

  1. /******************************************************************************
  2. * SBsp_Sym.c - Bspline surface symbolic computation.                  *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Sep. 92.                          *
  5. ******************************************************************************/
  6.  
  7. #include "symb_loc.h"
  8.  
  9. #define NODE_EQUAL_SHIFT 0.8
  10.  
  11. static int
  12.     BspMultUsingInterpolation = TRUE;
  13.  
  14. static CagdCrvStruct *BspCrvMultAux(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2);
  15. static CagdSrfStruct *BspSrfMultAux(CagdSrfStruct *Srf1, CagdSrfStruct *Srf2);
  16.  
  17. /*****************************************************************************
  18. * DESCRIPTION:                                                               M
  19. * Sets method of Bspline product computation.                                M
  20. *                                                                            *
  21. * PARAMETERS:                                                                M
  22. *   BspMultUsingInter:  If TRUE, Bspline product iscomputed by setting an    M
  23. *                       interpolation problem. Otherwise, by decomposing the M
  24. *                       Bspline geometry to Bezier geometry.             M
  25. *                                                                            *
  26. * RETURN VALUE:                                                              M
  27. *   int:         Previous setting.                                           M
  28. *                                                                            *
  29. * KEYWORDS:                                                                  M
  30. *   BspMultInterpFlag, product                                              M
  31. *****************************************************************************/
  32. int BspMultInterpFlag(int BspMultUsingInter)
  33. {
  34.     int i = BspMultUsingInterpolation;
  35.  
  36.     BspMultUsingInterpolation = BspMultUsingInter;
  37.     return i;
  38. }
  39.  
  40. /*****************************************************************************
  41. * DESCRIPTION:                                                               M
  42. * Given two Bspline curves - multiply them coordinatewise.             M
  43. *   The two curves are promoted to same point type before the multiplication M
  44. * can take place.                                 M
  45. *   See also BspMultInterpFlag.                                              M
  46. *                                                                            *
  47. * PARAMETERS:                                                                M
  48. *   Crv1, Crv2:   The two curves to multiply.                                M
  49. *                                                                            *
  50. * RETURN VALUE:                                                              M
  51. *   CagdCrvStruct *:  The product Crv1 * Crv2 coordinatewise.                M
  52. *                                                                            *
  53. * KEYWORDS:                                                                  M
  54. *   BspCrvMult, product                                                      M
  55. *****************************************************************************/
  56. CagdCrvStruct *BspCrvMult(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
  57. {
  58.     CagdCrvStruct *ProdCrv, *TCrv;
  59.  
  60.     Crv1 = CagdCrvCopy(Crv1);
  61.     Crv2 = CagdCrvCopy(Crv2);
  62.  
  63.     if (!CagdMakeCrvsCompatible(&Crv1, &Crv2, FALSE, FALSE))
  64.     SYMB_FATAL_ERROR(SYMB_ERR_CRV_FAIL_CMPT);
  65.  
  66.     if (BspMultUsingInterpolation) {
  67.     CagdPointType
  68.         PType = Crv1 -> PType;
  69.     CagdBType
  70.         IsRational = CAGD_IS_RATIONAL_PT(PType);
  71.     int i, j, KVLen, ResLength,
  72.         NumCoords = CAGD_NUM_OF_PT_COORD(PType),
  73.         ResOrder = Crv1 -> Order + Crv2 -> Order - 1;
  74.     CagdRType *R,
  75.         *KV = BspKnotContinuityMergeTwo(Crv1 -> KnotVector,
  76.                         Crv1 -> Length + Crv1 -> Order,
  77.                         Crv1 -> Order,
  78.                         Crv2 -> KnotVector,
  79.                         Crv2 -> Length + Crv2 -> Order,
  80.                         Crv2 -> Order,
  81.                         ResOrder, &KVLen),
  82.         *KVNodes = BspKnotNodes(KV, KVLen, ResOrder);
  83.     CagdCtlPtStruct
  84.         *CtlPt = NULL,
  85.         *CtlPtList = NULL;
  86.  
  87.     ResLength = KVLen - ResOrder;
  88.  
  89.     /* Verify that all nodes are distinct. */
  90.     for (i = 0, R = KVNodes; i < ResLength; i++, R++) {
  91.         if (APX_EQ(R[0], R[1])) {
  92.         if (i > 0)
  93.             R[0] = R[0] * NODE_EQUAL_SHIFT +
  94.                R[-1] * (1 - NODE_EQUAL_SHIFT);
  95.         }
  96.     }
  97.  
  98.     /* Evaluate the multiplication at the node values. */
  99.     for (i = 0, R = KVNodes; i < ResLength; i++, R++) {
  100.         CagdRType *Evl;
  101.  
  102.         if (CtlPt == NULL)
  103.         CtlPt = CtlPtList = CagdCtlPtNew(PType);
  104.         else {
  105.         CtlPt -> Pnext = CagdCtlPtNew(PType);
  106.         CtlPt = CtlPt -> Pnext;
  107.         }
  108.  
  109.         Evl = CagdCrvEval(Crv1, *R);
  110.         SYMB_GEN_COPY(CtlPt -> Coords, Evl,
  111.               CAGD_MAX_PT_SIZE * sizeof(CagdRType));
  112.         Evl = CagdCrvEval(Crv2, *R);
  113.         for (j = !IsRational; j <= NumCoords; j++)
  114.             CtlPt -> Coords[j] *= Evl[j];
  115.     }
  116.  
  117.     ProdCrv = BspCrvInterpolate(CtlPtList, ResLength, KVNodes, KV,
  118.                     ResLength, ResOrder, FALSE);
  119.     IritFree((VoidPtr) KVNodes);
  120.     CagdCtlPtFreeList(CtlPtList);
  121.     }
  122.     else {
  123.     TCrv = BspCrvMultAux(Crv1, Crv2);
  124.  
  125.     if (CAGD_IS_BEZIER_CRV(TCrv)) {
  126.         ProdCrv = CnvrtBezier2BsplineCrv(TCrv);
  127.         CagdCrvFree(TCrv);
  128.     }
  129.     else
  130.         ProdCrv = TCrv;
  131.     }
  132.  
  133.     CagdCrvFree(Crv1);
  134.     CagdCrvFree(Crv2);
  135.  
  136.     return ProdCrv;
  137. }
  138.  
  139. /*****************************************************************************
  140. * DESCRIPTION:                                                               *
  141. * Auxiliary routine. Subdivides the curves into Bezier curves, multiply      *
  142. * the Bezier curves and merge them back. All is done simultaneously.         *
  143. *                                                                            *
  144. * PARAMETERS:                                                                *
  145. *   Crv1, Crv2:   The two curves to multiply.                                *
  146. *                                                                            *
  147. * RETURN VALUE:                                                              *
  148. *   CagdCrvStruct *:  The product Crv1 * Crv2 coordinatewise.                *
  149. *****************************************************************************/
  150. static CagdCrvStruct *BspCrvMultAux(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
  151. {
  152.     CagdCrvStruct *Crv1a, *Crv1b, *Crv2a, *Crv2b, *CrvA, *CrvB, *ProdCrv;
  153.  
  154.     if (Crv1 -> Order != Crv1 -> Length ||
  155.     Crv2 -> Order != Crv2 -> Length) {
  156.     CagdRType SubdivVal = Crv1 -> Order != Crv1 -> Length ?
  157.                 Crv1 -> KnotVector[(Crv1 -> Length +
  158.                             Crv1 -> Order) / 2] :
  159.                 Crv2 -> KnotVector[(Crv2 -> Length +
  160.                             Crv2 -> Order) / 2];
  161.  
  162.     /* Subdivide. */
  163.     Crv1a = BspCrvSubdivAtParam(Crv1, SubdivVal);
  164.     Crv1b = Crv1a -> Pnext;
  165.     Crv1a -> Pnext = NULL;
  166.  
  167.     Crv2a = BspCrvSubdivAtParam(Crv2, SubdivVal);
  168.     Crv2b = Crv2a -> Pnext;
  169.     Crv2a -> Pnext = NULL;
  170.  
  171.     CrvA = BspCrvMultAux(Crv1a, Crv2a);
  172.     CrvB = BspCrvMultAux(Crv1b, Crv2b);
  173.     CagdCrvFree(Crv1a);
  174.     CagdCrvFree(Crv1b);
  175.     CagdCrvFree(Crv2a);
  176.     CagdCrvFree(Crv2b);
  177.  
  178.     ProdCrv = CagdMergeCrvCrv(CrvA, CrvB, FALSE);
  179.     CagdCrvFree(CrvA);
  180.     CagdCrvFree(CrvB);
  181.     }
  182.     else {
  183.     int i;
  184.     CagdRType TMin, TMax;
  185.     CagdCrvStruct
  186.         *Crv1Bzr = CnvrtBspline2BezierCrv(Crv1),
  187.         *Crv2Bzr = CnvrtBspline2BezierCrv(Crv2),
  188.         *ProdCrvAux = BzrCrvMult(Crv1Bzr, Crv2Bzr);
  189.  
  190.     CagdCrvDomain(Crv1, &TMin, &TMax);
  191.     ProdCrv = CnvrtBezier2BsplineCrv(ProdCrvAux);
  192.     for (i = 0; i < ProdCrv -> Order; i++) {
  193.         ProdCrv -> KnotVector[i] = TMin;
  194.         ProdCrv -> KnotVector[i + ProdCrv -> Order] = TMax;
  195.     }
  196.  
  197.     CagdCrvFree(Crv1Bzr);
  198.     CagdCrvFree(Crv2Bzr);
  199.     CagdCrvFree(ProdCrvAux);
  200.     }
  201.  
  202.     return ProdCrv;
  203. }
  204.  
  205. /*****************************************************************************
  206. * DESCRIPTION:                                                               M
  207. * Given two Bspline surfaces - multiply them coordinatewise.             M
  208. *   The two surfaces are promoted to same point type before multiplication   M
  209. * can take place.                                 M
  210. *   See also BspMultInterpFlag.                                              M
  211. *                                                                            *
  212. * PARAMETERS:                                                                M
  213. *   Srf1, Srf2:   The two surfaces to multiply.                             M
  214. *                                                                            *
  215. * RETURN VALUE:                                                              M
  216. *   CagdSrfStruct *:  The product Srf1 * Srf2 coordinatewise.                M
  217. *                                                                            *
  218. * KEYWORDS:                                                                  M
  219. *   BspSrfMult, product                                                      M
  220. *****************************************************************************/
  221. CagdSrfStruct *BspSrfMult(CagdSrfStruct *Srf1, CagdSrfStruct *Srf2)
  222. {
  223.     CagdSrfStruct *ProdSrf, *TSrf;
  224.  
  225.     Srf1 = CagdSrfCopy(Srf1);
  226.     Srf2 = CagdSrfCopy(Srf2);
  227.     if (!CagdMakeSrfsCompatible(&Srf1, &Srf2, FALSE, FALSE, FALSE, FALSE))
  228.     SYMB_FATAL_ERROR(SYMB_ERR_SRF_FAIL_CMPT);
  229.  
  230.     TSrf = BspSrfMultAux(Srf1, Srf2);
  231.  
  232.     if (CAGD_IS_BEZIER_SRF(TSrf)) {
  233.     ProdSrf = CnvrtBezier2BsplineSrf(TSrf);
  234.     CagdSrfFree(TSrf);
  235.     }
  236.     else
  237.     ProdSrf = TSrf;
  238.  
  239.     CagdSrfFree(Srf1);
  240.     CagdSrfFree(Srf2);
  241.  
  242.     return ProdSrf;
  243. }
  244.  
  245. /*****************************************************************************
  246. * DESCRIPTION:                                                               *
  247. * Auxiliary routine. Subdivides the surfaces into Bezier surfaces, multiply  *
  248. * the Bezier surfaces and merge them back. All is done simultaneously.       *
  249. *                                                                            *
  250. * PARAMETERS:                                                                *
  251. *   Srf1, Srf2:   The two surfaces to multiply.                              *
  252. *                                                                            *
  253. * RETURN VALUE:                                                              *
  254. *   CagdSrfStruct *:  The product Srf1 * Srf2 coordinatewise.                *
  255. *****************************************************************************/
  256. static CagdSrfStruct *BspSrfMultAux(CagdSrfStruct *Srf1, CagdSrfStruct *Srf2)
  257. {
  258.     CagdSrfStruct *Srf1a, *Srf1b, *Srf2a, *Srf2b, *SrfA, *SrfB, *ProdSrf;
  259.  
  260.     if (Srf1 -> UOrder != Srf1 -> ULength ||
  261.     Srf2 -> UOrder != Srf2 -> ULength) {
  262.     CagdRType
  263.         SubdivVal = Srf1 -> UOrder != Srf1 -> ULength ?
  264.                 Srf1 -> UKnotVector[(Srf1 -> ULength +
  265.                              Srf1 -> UOrder) / 2] :
  266.                 Srf2 -> UKnotVector[(Srf2 -> ULength +
  267.                              Srf2 -> UOrder) / 2];
  268.  
  269.     /* Subdivide along U. */
  270.     Srf1a = BspSrfSubdivAtParam(Srf1, SubdivVal, CAGD_CONST_U_DIR);
  271.     Srf1b = Srf1a -> Pnext;
  272.     Srf1a -> Pnext = NULL;
  273.  
  274.     Srf2a = BspSrfSubdivAtParam(Srf2, SubdivVal, CAGD_CONST_U_DIR);
  275.     Srf2b = Srf2a -> Pnext;
  276.     Srf2a -> Pnext = NULL;
  277.  
  278.     SrfA = BspSrfMultAux(Srf1a, Srf2a);
  279.     SrfB = BspSrfMultAux(Srf1b, Srf2b);
  280.     CagdSrfFree(Srf1a);
  281.     CagdSrfFree(Srf1b);
  282.     CagdSrfFree(Srf2a);
  283.     CagdSrfFree(Srf2b);
  284.  
  285.     ProdSrf = CagdMergeSrfSrf(SrfA, SrfB, CAGD_CONST_U_DIR, FALSE, FALSE);
  286.     CagdSrfFree(SrfA);
  287.     CagdSrfFree(SrfB);
  288.     }
  289.     else if (Srf1 -> VOrder != Srf1 -> VLength ||
  290.          Srf2 -> VOrder != Srf2 -> VLength) {
  291.     CagdRType
  292.         SubdivVal = Srf1 -> VOrder != Srf1 -> VLength ?
  293.                 Srf1 -> VKnotVector[(Srf1 -> VLength +
  294.                              Srf1 -> VOrder) / 2] :
  295.                 Srf2 -> VKnotVector[(Srf2 -> VLength +
  296.                              Srf2 -> VOrder) / 2];
  297.  
  298.     /* Subdivide along V. */
  299.     Srf1a = BspSrfSubdivAtParam(Srf1, SubdivVal, CAGD_CONST_V_DIR);
  300.     Srf1b = Srf1a -> Pnext;
  301.     Srf1a -> Pnext = NULL;
  302.  
  303.     Srf2a = BspSrfSubdivAtParam(Srf2, SubdivVal, CAGD_CONST_V_DIR);
  304.     Srf2b = Srf2a -> Pnext;
  305.     Srf2a -> Pnext = NULL;
  306.  
  307.     SrfA = BspSrfMultAux(Srf1a, Srf2a);
  308.     SrfB = BspSrfMultAux(Srf1b, Srf2b);
  309.     CagdSrfFree(Srf1a);
  310.     CagdSrfFree(Srf1b);
  311.     CagdSrfFree(Srf2a);
  312.     CagdSrfFree(Srf2b);
  313.  
  314.     ProdSrf = CagdMergeSrfSrf(SrfA, SrfB, CAGD_CONST_V_DIR, FALSE, FALSE);
  315.     CagdSrfFree(SrfA);
  316.     CagdSrfFree(SrfB);
  317.     }
  318.     else {
  319.     int i;
  320.     CagdRType UMin, UMax, VMin, VMax;
  321.     CagdSrfStruct
  322.         *Srf1Bzr = CnvrtBspline2BezierSrf(Srf1),
  323.         *Srf2Bzr = CnvrtBspline2BezierSrf(Srf2),
  324.         *ProdSrfAux = BzrSrfMult(Srf1Bzr, Srf2Bzr);
  325.  
  326.     CagdSrfDomain(Srf1, &UMin, &UMax, &VMin, &VMax);
  327.     ProdSrf = CnvrtBezier2BsplineSrf(ProdSrfAux);
  328.     for (i = 0; i < ProdSrf -> UOrder; i++) {
  329.         ProdSrf -> UKnotVector[i] = UMin;
  330.         ProdSrf -> UKnotVector[i + ProdSrf -> UOrder] = UMax;
  331.     }
  332.     for (i = 0; i < ProdSrf -> VOrder; i++) {
  333.         ProdSrf -> VKnotVector[i] = VMin;
  334.         ProdSrf -> VKnotVector[i + ProdSrf -> VOrder] = VMax;
  335.     }
  336.  
  337.     CagdSrfFree(Srf1Bzr);
  338.     CagdSrfFree(Srf2Bzr);
  339.     CagdSrfFree(ProdSrfAux);
  340.     }
  341.  
  342.     return ProdSrf;
  343. }
  344.  
  345. /*****************************************************************************
  346. * DESCRIPTION:                                                               M
  347. * Given a rational Bspline curve - computes its derivative curve (Hodograph) M
  348. * using the quotient rule for differentiation.                     M
  349. *                                                                            *
  350. * PARAMETERS:                                                                M
  351. *   Crv:         Bspline curve to differentiate.                             M
  352. *                                                                            *
  353. * RETURN VALUE:                                                              M
  354. *   CagdCrvStruct *:    Differentiated rational Bspline curve.               M
  355. *                                                                            *
  356. * KEYWORDS:                                                                  M
  357. *   BspCrvDeriveRational, derivatives                                        M
  358. *****************************************************************************/
  359. CagdCrvStruct *BspCrvDeriveRational(CagdCrvStruct *Crv)
  360. {
  361.     CagdCrvStruct *CrvW, *CrvX, *CrvY, *CrvZ, *TCrv1, *TCrv2, *DeriveCrv,
  362.         *DCrvW = NULL,
  363.     *DCrvX = NULL,
  364.     *DCrvY = NULL,
  365.     *DCrvZ = NULL;
  366.  
  367.     SymbCrvSplitScalar(Crv, &CrvW, &CrvX, &CrvY, &CrvZ);
  368.     if (CrvW)
  369.     DCrvW = BspCrvDerive(CrvW);
  370.     else
  371.     SYMB_FATAL_ERROR(SYMB_ERR_RATIONAL_EXPECTED);
  372.  
  373.     if (CrvX) {
  374.     DCrvX = BspCrvDerive(CrvX);
  375.  
  376.     TCrv1 = BspCrvMult(DCrvX, CrvW);
  377.     TCrv2 = BspCrvMult(CrvX, DCrvW);
  378.  
  379.     CagdCrvFree(CrvX);
  380.     CrvX = SymbCrvSub(TCrv1, TCrv2);
  381.     CagdCrvFree(TCrv1);
  382.     CagdCrvFree(TCrv2);
  383.     }
  384.     if (CrvY) {
  385.     DCrvY = BspCrvDerive(CrvY);
  386.  
  387.     TCrv1 = BspCrvMult(DCrvY, CrvW);
  388.     TCrv2 = BspCrvMult(CrvY, DCrvW);
  389.  
  390.     CagdCrvFree(CrvY);
  391.     CrvY = SymbCrvSub(TCrv1, TCrv2);
  392.     CagdCrvFree(TCrv1);
  393.     CagdCrvFree(TCrv2);
  394.     }
  395.     if (CrvZ) {
  396.     DCrvZ = BspCrvDerive(CrvZ);
  397.  
  398.     TCrv1 = BspCrvMult(DCrvZ, CrvW);
  399.     TCrv2 = BspCrvMult(CrvZ, DCrvW);
  400.  
  401.     CagdCrvFree(CrvZ);
  402.     CrvZ = SymbCrvSub(TCrv1, TCrv2);
  403.     CagdCrvFree(TCrv1);
  404.     CagdCrvFree(TCrv2);
  405.     }
  406.     
  407.     TCrv1 = BspCrvMult(CrvW, CrvW);
  408.     CagdCrvFree(CrvW);
  409.     CrvW = TCrv1;
  410.  
  411.     if (!CagdMakeCrvsCompatible(&CrvW, &CrvX, TRUE, TRUE) ||
  412.     !CagdMakeCrvsCompatible(&CrvW, &CrvY, TRUE, TRUE) ||
  413.     !CagdMakeCrvsCompatible(&CrvW, &CrvZ, TRUE, TRUE))
  414.     SYMB_FATAL_ERROR(SYMB_ERR_CRV_FAIL_CMPT);
  415.  
  416.     DeriveCrv = SymbCrvMergeScalar(CrvW, CrvX, CrvY, CrvZ);
  417.  
  418.     if (CrvX) {
  419.     CagdCrvFree(CrvX);
  420.     CagdCrvFree(DCrvX);
  421.     }
  422.     if (CrvY) {
  423.     CagdCrvFree(CrvY);
  424.     CagdCrvFree(DCrvY);
  425.     }
  426.     if (CrvZ) {
  427.     CagdCrvFree(CrvZ);
  428.     CagdCrvFree(DCrvZ);
  429.     }
  430.     if (CrvW) {
  431.     CagdCrvFree(CrvW);
  432.     CagdCrvFree(DCrvW);
  433.     }
  434.  
  435.     return DeriveCrv;
  436. }
  437.  
  438. /*****************************************************************************
  439. * DESCRIPTION:                                                               M
  440. * Given a rational Bspline surface - computes its derivative surface in      M
  441. * direction Dir, using the quotient rule for differentiation.             M
  442. *                                                                            *
  443. * PARAMETERS:                                                                M
  444. *   Srf:         Bspline surface to differentiate.                           M
  445. *   Dir:         Direction of Differentiation. Either U or V.                M
  446. *                                                                            *
  447. * RETURN VALUE:                                                              M
  448. *   CagdSrfStruct *:    Differentiated rational Bspline surface.             M
  449. *                                                                            *
  450. * KEYWORDS:                                                                  M
  451. *   BspSrfDeriveRational, derivatives                                        M
  452. *****************************************************************************/
  453. CagdSrfStruct *BspSrfDeriveRational(CagdSrfStruct *Srf, CagdSrfDirType Dir)
  454. {
  455.     CagdSrfStruct *SrfW, *SrfX, *SrfY, *SrfZ, *TSrf1, *TSrf2, *DeriveSrf,
  456.         *DSrfW = NULL,
  457.     *DSrfX = NULL,
  458.     *DSrfY = NULL,
  459.     *DSrfZ = NULL;
  460.  
  461.     SymbSrfSplitScalar(Srf, &SrfW, &SrfX, &SrfY, &SrfZ);
  462.     if (SrfW)
  463.     DSrfW = BspSrfDerive(SrfW, Dir);
  464.     else
  465.     SYMB_FATAL_ERROR(SYMB_ERR_RATIONAL_EXPECTED);
  466.  
  467.     if (SrfX) {
  468.     DSrfX = BspSrfDerive(SrfX, Dir);
  469.  
  470.     TSrf1 = BspSrfMult(DSrfX, SrfW);
  471.     TSrf2 = BspSrfMult(SrfX, DSrfW);
  472.  
  473.     CagdSrfFree(SrfX);
  474.     SrfX = SymbSrfSub(TSrf1, TSrf2);
  475.     CagdSrfFree(TSrf1);
  476.     CagdSrfFree(TSrf2);
  477.     }
  478.     if (SrfY) {
  479.     DSrfY = BspSrfDerive(SrfY, Dir);
  480.  
  481.     TSrf1 = BspSrfMult(DSrfY, SrfW);
  482.     TSrf2 = BspSrfMult(SrfY, DSrfW);
  483.  
  484.     CagdSrfFree(SrfY);
  485.     SrfY = SymbSrfSub(TSrf1, TSrf2);
  486.     CagdSrfFree(TSrf1);
  487.     CagdSrfFree(TSrf2);
  488.     }
  489.     if (SrfZ) {
  490.     DSrfZ = BspSrfDerive(SrfZ, Dir);
  491.  
  492.     TSrf1 = BspSrfMult(DSrfZ, SrfW);
  493.     TSrf2 = BspSrfMult(SrfZ, DSrfW);
  494.  
  495.     CagdSrfFree(SrfZ);
  496.     SrfZ = SymbSrfSub(TSrf1, TSrf2);
  497.     CagdSrfFree(TSrf1);
  498.     CagdSrfFree(TSrf2);
  499.     }
  500.     
  501.     TSrf1 = BspSrfMult(SrfW, SrfW);
  502.     CagdSrfFree(SrfW);
  503.     SrfW = TSrf1;
  504.  
  505.     if (!CagdMakeSrfsCompatible(&SrfW, &SrfX, TRUE, TRUE, TRUE, TRUE) ||
  506.     !CagdMakeSrfsCompatible(&SrfW, &SrfY, TRUE, TRUE, TRUE, TRUE) ||
  507.     !CagdMakeSrfsCompatible(&SrfW, &SrfZ, TRUE, TRUE, TRUE, TRUE))
  508.     SYMB_FATAL_ERROR(SYMB_ERR_SRF_FAIL_CMPT);
  509.  
  510.     DeriveSrf = SymbSrfMergeScalar(SrfW, SrfX, SrfY, SrfZ);
  511.  
  512.     if (SrfX) {
  513.     CagdSrfFree(SrfX);
  514.     CagdSrfFree(DSrfX);
  515.     }
  516.     if (SrfY) {
  517.     CagdSrfFree(SrfY);
  518.     CagdSrfFree(DSrfY);
  519.     }
  520.     if (SrfZ) {
  521.     CagdSrfFree(SrfZ);
  522.     CagdSrfFree(DSrfZ);
  523.     }
  524.     if (SrfW) {
  525.     CagdSrfFree(SrfW);
  526.     CagdSrfFree(DSrfW);
  527.     }
  528.  
  529.     return DeriveSrf;
  530. }
  531.